# coding=utf-8
from __future__ import print_function, absolute_import
from gm.api import *

def init(context):
    # 每天14:50 定时执行algo任务,
    # algo执行定时任务函数，只能传context参数
    # date_rule执行频率，目前暂时支持1d、1w、1m，其中1w、1m仅用于回测，实时模式1d以上的频率，需要在algo判断日期
    # time_rule执行时间， 注意多个定时任务设置同一个时间点，前面的定时任务会被后面的覆盖
    schedule(schedule_func=algo, date_rule='1m', time_rule='09:30:00')
    # 定义股票池数量
    context.num = 10


def algo(context):
    # 获取当前全A股票代码
    symbol_info = get_instrumentinfos(sec_types=SEC_TYPE_STOCK, fields='symbol,listed_date,delisted_date', df=True)
    # 剔除未上市、已退市的股票
    symbol_info = symbol_info[(symbol_info['listed_date']<context.now) & (symbol_info['delisted_date']>context.now)]
    # 剔除ST股票、停牌股
    symbol_info = get_history_instruments(symbols=list(symbol_info['symbol']), start_date=context.now, end_date=context.now, fields='symbol,sec_level,is_suspended', df=True)
    symbol_info = symbol_info[(symbol_info['sec_level']==1) & (symbol_info['is_suspended']==0)]
    # 剔除B股
    symbols = [code for code in list(symbol_info['symbol']) if code[:6]!='SHSE.9' and code[:6]!='SZSE.2']
    # 上一交易日
    last_date = get_previous_trading_date(exchange='SZSE', date=context.now)
    # 获取所有股票市值,并按升序排序
    fundamental = get_fundamentals_n(table='trading_derivative_indicator',symbols=symbols,end_date=last_date,count=1,fields='TOTMKTCAP',df=True).sort_values(by='TOTMKTCAP')
    
    # 获取前N只股票
    to_buy = list(fundamental.iloc[:context.num,:]['symbol'])
    print('本次股票池有股票数目: ', len(to_buy))

    positions = context.account().positions()
    # 平不在标的池的股票
    sell_symbols = []
    for position in positions:
        symbol = position['symbol']
        if symbol not in to_buy:
            order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Market,position_side=PositionSide_Long)
            sell_symbols.append(symbol)
    print('{},市价单卖出股票:{}'.format(context.now,sell_symbols))

    # 获取股票的权重
    percent = 1 / len(to_buy)
    # 买在标的池中的股票
    buy_symbols = []
    for symbol in to_buy:
        order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,position_side=PositionSide_Long)
        buy_symbols.append(symbol)
    print('{},市价单买入股票:{}'.format(context.now,buy_symbols))


# 查看最终的回测结果
def on_backtest_finished(context, indicator):
    print(indicator)


if __name__ == '__main__':
    '''
        strategy_id策略ID, 由系统生成
        filename文件名, 请与本文件名保持一致
        mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST
        token绑定计算机的ID, 可在系统设置-密钥管理中生成
        backtest_start_time回测开始时间
        backtest_end_time回测结束时间
        backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
        backtest_initial_cash回测初始资金
        backtest_commission_ratio回测佣金比例
        backtest_slippage_ratio回测滑点比例
        '''
    run(strategy_id='cfc5c885-0cf2-11ed-979e-7c10c9b8dfd6',
        filename='main.py',
        mode=MODE_BACKTEST,
        token='9dc704d3ed377bc76c94e882baea6816e93eff27',
        backtest_start_time='2021-01-01 08:00:00',
        backtest_end_time='2022-07-26 16:00:00',
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=1000000,
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001)
